package com.ryl.yomall.activity.receiver;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import com.ryl.yomall.activity.mapper.SeckillGoodsMapper;
import com.ryl.yomall.activity.util.CacheHelper;
import com.ryl.yomall.activity.util.DateUtil;
import com.ryl.yomall.model.activity.SeckillGoods;
import com.ryl.yomall.model.activity.UserRecode;
import com.ryl.yomall.model.common.constant.RedisConst;
import com.ryl.yomall.rabbitmq.constant.MQConstant;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;


/**
 * @author ryl
 * 接收消息
 */
@Component
public class SeckillReceiver {


    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    //秒杀之监听到MQ中消息
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(value = MQConstant.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
                    exchange = @Exchange(value = MQConstant.EXCHANGE_DIRECT_SECKILL_USER),
                    key = MQConstant.ROUTING_SECKILL_USER
            )
    })
    public void receiverMessageSeckill(UserRecode userRecode,Message message ,Channel channel) throws Exception{

        Long skuId = userRecode.getSkuId();
        String userId = userRecode.getUserId();
//        1、状态位
        Object o = CacheHelper.get(skuId.toString());
        if(!"1".equals(o)){
            System.out.println("此时商品状态位表示无货");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            return;
        }
//        2、校验此用户是否已经买过了  setnx key v  如果存在了 就返回0 false  如果不存在 返回值 1 true
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(RedisConst.SECKILL_USER
                + userId + ":" + skuId, "V");
        if(!flag){
            System.out.println("此用户已经买过了");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            return;
        }
//        3、校验商品库存
        Object o1 = redisTemplate.opsForList().
                rightPop(RedisConst.SECKILL_STOCK_PREFIX + skuId);
        if(null == o1){
            System.out.println("已经没有了");
            //        没有 更新状态位
            //发消息  skuId:1
            redisTemplate.convertAndSend("seckillpush",
                    skuId + ":0");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            return;
        }
//        有  抢购成功
        redisTemplate.opsForValue().set(RedisConst.SECKILL_ORDERS + userId,skuId.toString());
        //。。。。。。。
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //接收MQ消息
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(value = MQConstant.QUEUE_TASK_1,durable = "true",autoDelete = "false"),
                    exchange = @Exchange(value = MQConstant.EXCHANGE_DIRECT_TASK),
                    key = MQConstant.ROUTING_TASK_1
            )
    })
    public void importDataToRedis(Message message,Channel channel) throws Exception {
        System.out.println ("接收到消息:"+ Arrays.toString ( message.getBody ( ) ) );

        //导入秒杀商品数据到Redis中
        QueryWrapper<SeckillGoods> queryWrapper = new QueryWrapper<> ();
        //审核状态 0：未审核  1：审核通过
        queryWrapper.eq("status","1");
        //库存大于0
        queryWrapper.gt("stock_count",0);

        //开始时间//结束时间  现在是凌晨一点  只要在今天
        queryWrapper.eq("DATE_FORMAT(start_time,'%Y-%m-%d')", DateUtil.formatDate(new Date ()));

        //1:查询秒杀商品数据
        List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(queryWrapper);

        if(!CollectionUtils.isEmpty(seckillGoodsList)){
            seckillGoodsList.forEach(seckillGoods -> {
                if(!redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_GOODS,
                                seckillGoods.getSkuId().toString())){

                //保存缓存中
                Long skuId = seckillGoods.getSkuId();
                redisTemplate.opsForHash().put( RedisConst.SECKILL_GOODS, skuId.toString (),seckillGoods);
                //根据每一款商品的数量  准备集合
                String[] skuIds = new String[seckillGoods.getStockCount()];
                for (Integer i = 0; i < seckillGoods.getStockCount(); i++) {
                    skuIds[i] = skuId.toString ();
                }
                redisTemplate.opsForList().leftPushAll(RedisConst.SECKILL_STOCK_PREFIX + skuId.toString (),skuIds);
                    //3:状态位
                    //发消息  skuId:1
                redisTemplate.convertAndSend("seckillpush",
                            seckillGoods.getSkuId() + ":1");
                }
            });
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
    /**
     * 秒杀结束清空缓存
     *
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MQConstant.QUEUE_TASK_18, durable = "true"),
            exchange = @Exchange(value = MQConstant.EXCHANGE_DIRECT_TASK, type = ExchangeTypes.DIRECT, durable = "true"),
            key = {MQConstant.ROUTING_TASK_18}
    ))
    public void clearRedis(Message message, Channel channel) throws IOException {

        //活动结束清空缓存
        QueryWrapper<SeckillGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1);
        queryWrapper.le("end_time", new Date());
        List<SeckillGoods> list = seckillGoodsMapper.selectList(queryWrapper);
        //清空缓存
        for (SeckillGoods seckillGoods : list) {
            redisTemplate.delete(RedisConst.SECKILL_STOCK_PREFIX + seckillGoods.getSkuId());
        }
        redisTemplate.delete(RedisConst.SECKILL_GOODS);
        redisTemplate.delete(RedisConst.SECKILL_ORDERS);
        redisTemplate.delete(RedisConst.SECKILL_ORDERS_USERS);
        //将状态更新为结束
        SeckillGoods seckillGoodsUp = new SeckillGoods();
        seckillGoodsUp.setStatus("2");
        seckillGoodsMapper.update(seckillGoodsUp, queryWrapper);
        // 手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }


}
